#include "qf_pkg.h"
#include "qassert.h"
#include <raw_api.h>

Q_DEFINE_THIS_MODULE("qf_port")


void qf_port_tick() 
{
    QF_TICK();
}



/*..........................................................................*/
char const Q_ROM * Q_ROM_VAR QF_getPortVersion(void) {
    static const char Q_ROM Q_ROM_VAR version[] =  "4.4.00";
    return version;
}


/*..........................................................................*/
void QF_init(void) {
   
}
/*..........................................................................*/
int16_t QF_run(void) {
                                 
    return (int16_t)0;  /* this unreachable return keeps the compiler happy */
}
/*..........................................................................*/
void QF_stop(void) {
	QF_CRIT_STAT_
	QF_CRIT_ENTRY_();
	QF_CRIT_EXIT_();                                    /* cleanup callback */
}
/*..........................................................................*/
static void task_function(void *pdata) {         /* uC/OS-II task signature */
    while (((QActive *)pdata)->user_data != (uint8_t)0) {
        QEvt const *e = QActive_get_((QActive *)pdata);
        QF_ACTIVE_DISPATCH_(&((QActive *)pdata)->super, e);
        QF_gc(e);    /* check if the event is garbage, and collect it if so */
    }

    QF_remove_((QActive *)pdata);  /* remove this object from the framework */
    raw_task_delete(raw_task_identify());
}
/*..........................................................................*/


void QActive_start(QActive * const me, uint8_t prio,
                   QEvt const *qSto[], uint32_t qLen,
                   void *stkSto, uint32_t stkSize,
                   QEvt const *ie)

{
    RAW_U16 err;

	raw_queue_create(&me->eQueue, (RAW_U8 *)"queue", (void **)qSto, qLen);
	
    me->prio = prio;                                /* save the QF priority */
    QF_add_(me);                     /* make QF aware of this active object */
    QF_ACTIVE_INIT_(&me->super, ie);          /* execute initial transition */
	
    QS_FLUSH();                       /* flush the trace buffer to the host */
	
 	me->user_data = 1;
  
	err = raw_task_create(&me->thread, (RAW_U8  *)"task5", me,
	                         QF_MAX_ACTIVE - me->prio, 0,   stkSto, 
	                         stkSize, task_function, 1);
	
    Q_ASSERT(err == RAW_SUCCESS);                    /* uC/OS-II task created */
}
/*..........................................................................*/
void QActive_stop(QActive * const me) {
    RAW_U16 err;
    me->user_data = (uint8_t)0;                        /* stop the thread loop */
	err = raw_queue_delete(&me->eQueue);
    Q_ASSERT(err == RAW_SUCCESS);
}
/*..........................................................................*/
#ifndef Q_SPY
 void QActive_postFIFO(QActive * const me, QEvt const * const e){
#else
void QActive_postFIFO(QActive * const me, QEvt const *e, void const *sender) {
#endif

    QF_CRIT_STAT_
    QF_CRIT_ENTRY_();

    QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_FIFO, QS_aoObj_, me)
        QS_TIME_();                                            /* timestamp */
        QS_OBJ_(sender);                               /* the sender object */
        QS_SIG_(e->sig);                         /* the signal of the event */
        QS_OBJ_(me);                      /* this active object (recipient) */
        QS_U8_(QF_EVT_POOL_ID_(e));             /* the pool Id of the event */
        QS_U8_(QF_EVT_REF_CTR_(e));           /* the ref count of the event */
        QS_EQC_(0);                     /* number of free entries (unknown) */
        QS_EQC_(0);                 /* min number of free entries (unknown) */
    QS_END_NOCRIT_()

    if (QF_EVT_POOL_ID_(e) != (uint8_t)0) {          /* is it a pool event? */
        QF_EVT_REF_CTR_INC_(e);          /* increment the reference counter */
    }
    QF_CRIT_EXIT_();
	Q_ALLEGE(raw_queue_end_post(&me->eQueue, (void *)e) == RAW_SUCCESS);
	
}
/*..........................................................................*/
void QActive_postLIFO(QActive * const me, QEvt const * const e){
    QF_CRIT_STAT_
    QF_CRIT_ENTRY_();

    QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_LIFO, QS_aoObj_, me)
        QS_TIME_();                                            /* timestamp */
        QS_SIG_(e->sig);                        /* the signal of this event */
        QS_OBJ_(me);                                  /* this active object */
        QS_U8_(QF_EVT_POOL_ID_(e));             /* the pool Id of the event */
        QS_U8_(QF_EVT_REF_CTR_(e));           /* the ref count of the event */
        QS_EQC_(0);                     /* number of free entries (unknown) */
        QS_EQC_(0);                 /* min number of free entries (unknown) */
    QS_END_NOCRIT_()

    if (QF_EVT_POOL_ID_(e) != (uint8_t)0) {          /* is it a pool event? */
        QF_EVT_REF_CTR_INC_(e);          /* increment the reference counter */
    }
    QF_CRIT_EXIT_();
    Q_ALLEGE(raw_queue_front_post(&me->eQueue, (void *)e) == RAW_SUCCESS);
}
/*..........................................................................*/
QEvt const *QActive_get_(QActive *const me) {
    RAW_U16 err;
    QEvt const *e;

	err = raw_queue_receive (&me->eQueue, RAW_WAIT_FOREVER, (RAW_VOID  **)&e);
    QS_CRIT_STAT_

    Q_ASSERT(err == RAW_SUCCESS);

    QS_BEGIN_(QS_QF_ACTIVE_GET, QS_aoObj_, me)
        QS_TIME_();                                            /* timestamp */
        QS_SIG_(e->sig);                        /* the signal of this event */
        QS_OBJ_(me);                                  /* this active object */
        QS_U8_(QF_EVT_POOL_ID_(e));             /* the pool Id of the event */
        QS_U8_(QF_EVT_REF_CTR_(e));           /* the ref count of the event */
        QS_EQC_(0);                     /* number of free entries (unknown) */
    QS_END_()

    return e;
}


